#include <stdio.h>
#include <malloc.h>
#define INF 32767				//定义∞
#define	MAXV 100				//最大顶点个数
typedef char InfoType;

//以下定义邻接表类型
typedef struct ANode
{	int adjvex;					//该边的邻接点编号
	struct ANode *nextarc;		//指向下一条边的指针
	int weight;					//该边的相关信息，如权值（用整型表示）
} ArcNode;						//边结点类型

typedef struct Vnode
{	InfoType info;				//顶点其他信息
	int count;					//存放顶点入度,仅仅用于拓扑排序
	ArcNode *firstarc;			//指向第一条边
} VNode;						//邻接表头结点类型

typedef struct 
{	VNode adjlist[MAXV];		//邻接表头结点数组
	int n,e;					//图中顶点数n和边数e
} AdjGraph;						//完整的图邻接表类型


//------------------------------------------------------------
//----邻接表的基本运算算法------------------------------------
//------------------------------------------------------------
void CreateAdj(AdjGraph *&G,int A[MAXV][MAXV],int n,int e) //创建图的邻接表
{
	//n 个顶点
	//e 条边
	int i,j;
	ArcNode *p;
	G=(AdjGraph *)malloc(sizeof(AdjGraph));
	for (i=0;i<n;i++)								//给邻接表中所有头结点的指针域置初值
		G->adjlist[i].firstarc=NULL;
	for (i=0;i<n;i++)								//检查邻接矩阵中每个元素
		for (j=n-1;j>=0;j--)
			if (A[i][j]!=0 && A[i][j]!=INF)			//存在一条边
			{	p=(ArcNode *)malloc(sizeof(ArcNode));	//创建一个结点p
				p->adjvex=j;
				p->weight=A[i][j];
				p->nextarc=G->adjlist[i].firstarc;	//采用头插法插入结点p
				G->adjlist[i].firstarc=p;
			}
	G->n=n; G->e=n;
}
void DispAdj(AdjGraph *G)	//输出邻接表G
{
	int i;
	ArcNode *p;
	for (i=0;i<G->n;i++)
	{
		p=G->adjlist[i].firstarc;
		printf("%3d: ",i);
		while (p!=NULL)
		{
			printf("%3d[%d]→",p->adjvex,p->weight);
			p=p->nextarc;
		}
		printf("∧\n");
	}
	printf("\n");
}
void DestroyAdj(AdjGraph *&G)		//销毁图的邻接表
{	int i;
	ArcNode *pre,*p;
	for (i=0;i<G->n;i++)			//扫描所有的单链表
	{	pre=G->adjlist[i].firstarc;	//p指向第i个单链表的首结点
		if (pre!=NULL)
		{	p=pre->nextarc;
			while (p!=NULL)			//释放第i个单链表的所有边结点
			{	free(pre);
				pre=p; p=p->nextarc;
			}
			free(pre);
		}
	}
	free(G);						//释放头结点数组
}
//------------------------------------------------------------

void InsertEdge(AdjGraph *&G,int u,int v)
{
	ArcNode *p, *t, *q;
	if (u > G->n || u < 0 || v > G->n || v < 0)	printf("输入不合法！\n");
	else
	{	p = G->adjlist[u].firstarc;
		while (1)
		{	
			if (p == NULL)	break;
			if (p->adjvex == v){	
				printf("此边已存在！\n");
				return;
			}
			p = p->nextarc;
		}
		//if(p==NULL)
		t = (ArcNode *)malloc(sizeof(ArcNode));
		t->adjvex = v;
		//头插法
		t->nextarc = G->adjlist[u].firstarc;
		G->adjlist[u].firstarc = t;
		
		//
		q = (ArcNode *)malloc(sizeof(ArcNode));
		q->adjvex = u;
		q->nextarc = G->adjlist[v].firstarc;
		G->adjlist[v].firstarc = q; 
		G->e++;
	}
}


void IsExist(AdjGraph*&G,int u,int v)
{
	ArcNode *p;
	bool flag = true;
	if (u > G->n || u < 0 || v > G->n || v < 0)	flag = false;
	else{
		p = G->adjlist[u].firstarc;
		while (1)
		{	
			if (p == NULL){ flag = false;  break;}
			if (p->adjvex == v){	
				break;
			}
			p = p->nextarc;
		}
	}
	if(flag==true) printf("存在！\n");
	else if(flag==false) printf("不存在！\n");
	
}






int main()
{
	AdjGraph *G993;
	
	int a993[MAXV][MAXV] = {
		{0,1,0,1,1},
		{1,0,1,1,0},
		{0,1,0,1,1},
		{1,1,1,0,1},
		{1,0,1,1,0}
	};
	int n993 = 5;
	int e993 = 8;
	CreateAdj(G993,a993,n993,e993);
	DispAdj(G993);
	
	
	int x993 = 0,y993 = 0;
	printf("你要在哪两点之间插入边(输入两顶点)：>");
	scanf("%d%d",&x993,&y993);
	InsertEdge(G993,x993,y993);
	printf("插入后：\n");
	DispAdj(G993);
	
	printf("你要查看哪两点之间是否有边(输入两顶点)：");
	scanf("%d%d",&x993,&y993);
	IsExist(G993,x993,y993);
	
	
	
	
	DestroyAdj(G993);
	return 0;
}
